// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import work from 'webworkify-webpack';
import Logger from './Logger';
import getEvents from './tools/event';
import Util from './Util';
import BaseClass from './tools/baseClass';
import WebGLRenderer from './WebglRenderer';
import { CLOUD_PHONE_RATIO } from './config/commonConfig';

class CanvasPlayer extends BaseClass {
    constructor(options) {
        super(options);
        this.options = {...options};
        this.moduleInit = false;
        this.streamList = [];
        this.document = document;
        this.tinyH264Worker = null;
        this.videoStreamId = 1;
        this.util = new Util();

        this.options.events = getEvents();
        this.setCanvas();
        this.setImagerPlayer();

        //将本行代码放主线程执行
        this.tinyH264Worker = work(require.resolve('./worker/H264NALDecoderWorker.js'));
        this.tinyH264Worker.addEventListener('message', (e) => {
            const message = /** @type {{type:string, width:number, height:number, data:ArrayBuffer, renderStateId:number}} */e.data
            switch (message.type) {
              case 'pictureReady':
                const { width, height, data } = message;
                self.postMessage({
                  type: 'decoded',
                  data: {
                    data,
                    width,
                    height,
                  },
                });
                this.onRenderImage({
                  data,
                  width,
                  height,
                });
                break;
              case 'decoderReady':
                this.moduleInit = true;
                break;
            }
        });
      }

    setCanvas () {
        const $canvas = this.util.createCanvas(this.options.isMobile, CLOUD_PHONE_RATIO);
        // 放入元素内部
        let parentNode = document.getElementById('container');
        parentNode.appendChild($canvas);
        this.canvas = $canvas;
    }

    setImagerPlayer () {
        const canvas = document.getElementById('playCanvas');
        this.webglPlayer = new WebGLRenderer(canvas, {
            preserveDrawingBuffer: false
        });
    }

    onRenderImage(obj) {
      let unData = new Uint8Array(obj.data);
      let width = obj.width;
      let height = obj.height;
      let yLength = width * height;
      let uvLength = (width / 2) * (height / 2);
      if(!this.webglPlayer) {
        this.setImagerPlayer();
      }
      this.webglPlayer.renderFrame(unData, width, height, yLength, uvLength);
    }

    startDecod() {
      const streamData = this.streamList.shift();
      if (streamData && streamData.buffer) {
        this.tinyH264Worker.postMessage(
          {
            type: 'decode',
            data: streamData.buffer,
            offset: streamData.byteOffset,
            length: streamData.byteLength,
            renderStateId: this.videoStreamId,
          },
          [streamData.buffer],
        );
      } else {
          Logger.error('startDecode', 'data is null', 'data:', data)
      }
    }

    decode(data) {
        /*global __IS_DEBUG__*/
        if (__IS_DEBUG__) {
            let traceId = window.delayAnalysis.shiftTraceId('receive') || '';
            window.delayAnalysis.cacheTraceId('decode', traceId);
            window.delayAnalysis.record(['decode', 'start', traceId]);
        }

        // 暂存流数据，等解码器准备好后开始解码
        this.streamList.push(data);
        if (this.moduleInit) {
          this.startDecod();
        }
    }

    destroy() {
        this.tinyH264Worker.postMessage({ type: 'release', renderStateId: this.videoStreamId });
        this.tinyH264Worker.terminate();
    }
}

export default CanvasPlayer;
